package org.mat.ipaas.ucenter.bff.admin.modules.system;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.mat.framework.lang.dto.MatApiResponse;
import org.mat.ipaas.ucenter.service.api.system.SysDictRestAPI;
import org.mat.ipaas.ucenter.service.constant.CacheConstant;
import org.mat.ipaas.ucenter.service.dto.system.entity.SysDictDTO;
import org.mat.ipaas.ucenter.service.dto.system.model.SysDictTreeDTO;
import org.mat.ipaas.ucenter.service.dto.system.model.TreeSelectModelDTO;
import org.mat.ipaas.ucenter.service.dto.system.vo.DictModelDTO;
import org.mat.ipaas.ucenter.service.dto.system.vo.DictQueryDTO;
import org.mat.ipaas.ucenter.service.dto.system.vo.lowapp.SysDictVoDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * <p>
 * 字典表 前端控制器
 * </p>
 *
 * @Author zhangweijian
 * @since 2018-12-28
 */
@RestController
@RequestMapping("/sys/dict")
@Slf4j
public class SysDictController {

    @Autowired
    private SysDictRestAPI sysDictRestAPI;

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public MatApiResponse<Page<SysDictDTO>> queryPageList(SysDictDTO sysDict, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                          @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
        MatApiResponse<Page<SysDictDTO>> matApiResponse = sysDictRestAPI.queryPageList(sysDict, pageNo, pageSize);
        return matApiResponse;
    }

    /**
     * @param sysDictDTO
     * @param pageNo
     * @param pageSize
     * @return
     * @功能：获取树形字典数据
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/treeList", method = RequestMethod.GET)
    public MatApiResponse<List<SysDictTreeDTO>> treeList(@SpringQueryMap SysDictDTO sysDictDTO,
                                                         @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                         @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        MatApiResponse<List<SysDictTreeDTO>> matApiResponse = sysDictRestAPI.treeList(sysDictDTO, pageNo, pageSize);
        return matApiResponse;
    }

    /**
     * 获取全部字典数据
     *
     * @return
     */
    @RequestMapping(value = "/queryAllDictItems", method = RequestMethod.GET)
    public MatApiResponse<?> queryAllDictItems(HttpServletRequest request) {
        MatApiResponse<?> matApiResponse = sysDictRestAPI.queryAllDictItems(request);
        return matApiResponse;
    }

    /**
     * 获取字典数据
     *
     * @param dictCode
     * @return
     */
    @RequestMapping(value = "/getDictText/{dictCode}/{key}", method = RequestMethod.GET)
    public MatApiResponse<String> getDictText(@PathVariable("dictCode") String dictCode, @PathVariable("key") String key) {
        MatApiResponse<String> matApiResponse = sysDictRestAPI.getDictText(dictCode, key);
        return matApiResponse;
    }


    /**
     * 获取字典数据 【接口签名验证】
     *
     * @param dictCode 字典code
     * @param dictCode 表名,文本字段,code字段  | 举例：sys_user,realname,id
     * @return
     */
    @RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET)
    public MatApiResponse<List<DictModelDTO>> getDictItems(@PathVariable("dictCode") String dictCode, @RequestParam(value = "sign", required = false) String sign, HttpServletRequest request) {
        MatApiResponse<List<DictModelDTO>> matApiResponse = sysDictRestAPI.getDictItems(dictCode, sign, request);
        return matApiResponse;
    }

    /**
     * 【接口签名验证】
     * 【JSearchSelectTag下拉搜索组件专用接口】
     * 大数据量的字典表 走异步加载  即前端输入内容过滤数据
     *
     * @param dictCode 字典code格式：table,text,code
     * @return
     */
    @RequestMapping(value = "/loadDict/{dictCode}", method = RequestMethod.GET)
    public MatApiResponse<List<DictModelDTO>> loadDict(@PathVariable("dictCode") String dictCode,
                                                       @RequestParam(name = "keyword", required = false) String keyword,
                                                       @RequestParam(value = "sign", required = false) String sign,
                                                       @RequestParam(value = "pageSize", required = false) Integer pageSize) {

        MatApiResponse<List<DictModelDTO>> matApiResponse = sysDictRestAPI.loadDict(dictCode, keyword, sign, pageSize);
        return matApiResponse;
    }

    /**
     * 【接口签名验证】
     * 【给表单设计器的表字典使用】下拉搜索模式，有值时动态拼接数据
     *
     * @param dictCode
     * @param keyword  当前控件的值，可以逗号分割
     * @param sign
     * @param pageSize
     * @return
     */
    @RequestMapping(value = "/loadDictOrderByValue/{dictCode}", method = RequestMethod.GET)
    public MatApiResponse<List<DictModelDTO>> loadDictOrderByValue(
            @PathVariable("dictCode") String dictCode,
            @RequestParam(name = "keyword") String keyword,
            @RequestParam(value = "sign", required = false) String sign,
            @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        MatApiResponse<List<DictModelDTO>> matApiResponse = sysDictRestAPI.loadDictOrderByValue(dictCode, keyword, sign, pageSize);
        return matApiResponse;
    }

    /**
     * 【接口签名验证】
     * 根据字典code加载字典text 返回
     *
     * @param dictCode    顺序：tableName,text,code
     * @param keys        要查询的key
     * @param sign
     * @param delNotExist 是否移除不存在的项，默认为true，设为false如果某个key不存在数据库中，则直接返回key本身
     * @param request
     * @return
     */
    @RequestMapping(value = "/loadDictItem/{dictCode}", method = RequestMethod.GET)
    public MatApiResponse<List<String>> loadDictItem(@PathVariable("dictCode") String dictCode, @RequestParam(name = "key") String keys, @RequestParam(value = "sign", required = false) String sign, @RequestParam(value = "delNotExist", required = false, defaultValue = "true") boolean delNotExist, HttpServletRequest request) {
        MatApiResponse<List<String>> matApiResponse = sysDictRestAPI.loadDictItem(dictCode, keys, sign, delNotExist, request);
        return matApiResponse;
    }

    /**
     * 【接口签名验证】
     * 根据表名——显示字段-存储字段 pid 加载树形数据
     *
     * @param hasChildField   是否叶子节点字段
     * @param converIsLeafVal 是否需要系统转换 是否叶子节点的值 (0标识不转换、1标准系统自动转换)
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/loadTreeData", method = RequestMethod.GET)
    public MatApiResponse<List<TreeSelectModelDTO>> loadTreeData(@RequestParam(name = "pid", required = false) String pid, @RequestParam(name = "pidField") String pidField,
                                                                 @RequestParam(name = "tableName") String tbname,
                                                                 @RequestParam(name = "text") String text,
                                                                 @RequestParam(name = "code") String code,
                                                                 @RequestParam(name = "hasChildField") String hasChildField,
                                                                 @RequestParam(name = "converIsLeafVal", defaultValue = "1") int converIsLeafVal,
                                                                 @RequestParam(name = "condition") String condition,
                                                                 @RequestParam(value = "sign", required = false) String sign, HttpServletRequest request) {
        MatApiResponse<List<TreeSelectModelDTO>> matApiResponse = sysDictRestAPI.loadTreeData(pid, pidField, tbname, text, code, hasChildField, converIsLeafVal, condition, sign, request);
        return matApiResponse;
    }

    /**
     * 【APP接口】根据字典配置查询表字典数据（目前暂未找到调用的地方）
     *
     * @param dictQueryDTO
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Deprecated
    @GetMapping("/queryTableData")
    public MatApiResponse<List<DictModelDTO>> queryTableData(DictQueryDTO dictQueryDTO,
                                                             @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                             @RequestParam(value = "sign", required = false) String sign, HttpServletRequest request) {
        MatApiResponse<List<DictModelDTO>> matApiResponse = sysDictRestAPI.queryTableData(dictQueryDTO, pageNo, pageSize, sign, request);
        return matApiResponse;
    }

    /**
     * @param sysDictDTO
     * @return
     * @功能：新增
     */
    //@RequiresPermissions("system:dict:add")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public MatApiResponse<SysDictDTO> add(@RequestBody SysDictDTO sysDictDTO) {
        MatApiResponse<SysDictDTO> matApiResponse = sysDictRestAPI.add(sysDictDTO);
        return matApiResponse;
    }

    /**
     * @param sysDictDTO
     * @return
     * @功能：编辑
     */
    //@RequiresPermissions("system:dict:edit")
    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
    public MatApiResponse<SysDictDTO> edit(@RequestBody SysDictDTO sysDictDTO) {
        MatApiResponse<SysDictDTO> matApiResponse = sysDictRestAPI.edit(sysDictDTO);
        return matApiResponse;
    }

    /**
     * @param id
     * @return
     * @功能：删除
     */
    //@RequiresPermissions("system:dict:delete")
    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    @CacheEvict(value = {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries = true)
    public MatApiResponse<SysDictDTO> delete(@RequestParam(name = "id", required = true) String id) {
        MatApiResponse<SysDictDTO> matApiResponse = sysDictRestAPI.delete(id);
        return matApiResponse;
    }

    /**
     * @param ids
     * @return
     * @功能：批量删除
     */
    //@RequiresPermissions("system:dict:deleteBatch")
    @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
    @CacheEvict(value = {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries = true)
    public MatApiResponse<SysDictDTO> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        MatApiResponse<SysDictDTO> matApiResponse = sysDictRestAPI.deleteBatch(ids);
        return matApiResponse;
    }

    /**
     * @return
     * @功能：刷新缓存
     */
    @RequestMapping(value = "/refleshCache")
    public MatApiResponse<?> refleshCache() {
        MatApiResponse<?> matApiResponse = sysDictRestAPI.refleshCache();
        return matApiResponse;
    }

    /**
     * 导出excel
     *
     * @param sysDictDTO
     * @param request
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(SysDictDTO sysDictDTO, HttpServletRequest request) {
        ModelAndView modelAndView = sysDictRestAPI.exportXls(sysDictDTO, request);
        return modelAndView;
    }

    /**
     * 通过excel导入数据
     *
     * @param
     * @return
     */
    //@RequiresPermissions("system:dict:importExcel")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public MatApiResponse<?> importExcel() {
        MatApiResponse<?> matApiResponse = sysDictRestAPI.importExcel();
        return matApiResponse;
    }


    /**
     * 查询被删除的列表
     *
     * @return
     */
    @RequestMapping(value = "/deleteList", method = RequestMethod.GET)
    public MatApiResponse<List<SysDictDTO>> deleteList() {
        MatApiResponse<List<SysDictDTO>> matApiResponse = sysDictRestAPI.deleteList();
        return matApiResponse;
    }

    /**
     * 物理删除
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/deletePhysic/{id}", method = RequestMethod.DELETE)
    public MatApiResponse<?> deletePhysic(@PathVariable("id") String id) {
        MatApiResponse<?> matApiResponse = sysDictRestAPI.deletePhysic(id);
        return matApiResponse;
    }

    /**
     * 逻辑删除的字段，进行取回
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/back/{id}", method = RequestMethod.PUT)
    public MatApiResponse<?> back(@PathVariable("id") String id) {
        MatApiResponse<?> matApiResponse = sysDictRestAPI.back(id);
        return matApiResponse;
    }

    /**
     * VUEN-2584【issue】平台sql注入漏洞几个问题
     * 部分特殊函数 可以将查询结果混夹在错误信息中，导致数据库的信息暴露
     *
     * @param e
     * @return
     */
    @ExceptionHandler(java.sql.SQLException.class)
    public MatApiResponse<?> handleSQLException(Exception e) {
        String msg = e.getMessage();
        String extractvalue = "extractvalue";
        String updatexml = "updatexml";
        if (msg != null && (msg.toLowerCase().indexOf(extractvalue) >= 0 || msg.toLowerCase().indexOf(updatexml) >= 0)) {
            return MatApiResponse.fail("校验失败，sql解析异常！");
        }
        return MatApiResponse.fail("校验失败，sql解析异常！" + msg);
    }

    /**
     * 根据应用id获取字典列表和详情
     *
     * @param request
     */
    @GetMapping("/getDictListByLowAppId")
    public MatApiResponse<List<SysDictVoDTO>> getDictListByLowAppId(HttpServletRequest request) {
        MatApiResponse<List<SysDictVoDTO>> matApiResponse = sysDictRestAPI.getDictListByLowAppId(request);
        return matApiResponse;
    }

    /**
     * 添加字典
     *
     * @param sysDictVoDTO
     * @param request
     * @return
     */
    @PostMapping("/addDictByLowAppId")
    public MatApiResponse<String> addDictByLowAppId(@RequestBody SysDictVoDTO sysDictVoDTO, HttpServletRequest request) {
        MatApiResponse<String> matApiResponse = sysDictRestAPI.addDictByLowAppId(sysDictVoDTO, request);
        return matApiResponse;
    }

    @PutMapping("/editDictByLowAppId")
    public MatApiResponse<String> editDictByLowAppId(@RequestBody SysDictVoDTO sysDictVoDTO, HttpServletRequest request) {
        MatApiResponse<String> matApiResponse = sysDictRestAPI.editDictByLowAppId(sysDictVoDTO, request);
        return matApiResponse;
    }
}
